package com.apes.fn.controlling.innerAssist;

import com.apes.framework.api.SpringManager;
import com.apes.framework.query.SqlService;
import com.apes.framework.util.DateUtil;
import com.apestech.framework.json.JSONObject;
import lombok.Data;
import java.util.*;

/**
 * Creator: zouyc
 * CreateDate: 2021-04-20 10:35
 * Description:
 **/
@Data
public abstract class InnerEngine<R,T> implements InnerAssist{ //

    public static int maxMonth = 12;

    private String address;
    private JSONObject json;
    private boolean monthFlag = false;

    private boolean lastStage = false;

    private Date startDate;
    private Date endDate;

    SqlService sqlService;
    public InnerEngine(){
        sqlService = SpringManager.getBean(SqlService.class);
    }


    /**
     * 链式设置参数
     * @param address
     * @param json
     * @return
     */
    public InnerEngine setCondition(String address, JSONObject json,boolean monthFlag,boolean lastStage){
        this.address = address;
        this.json = json;

        this.monthFlag = monthFlag;
        this.lastStage = lastStage;
        return this;
    }




    public List findByAddressAndCondition(String address, JSONObject json){
        checkTime(json);
        return sqlService.queryId(address,json);
    }
     public R process(){
        List doList = null;
         T t = null;

         init(json);

         List list = findByAddressAndCondition(address,json); //查询

         doList = list;


         //增加月头部list
         if(monthFlag){
             List moththList = obtainMonthList(startDate,endDate); //作排序，以及限制数据差多了月份

             moththList.forEach(obj ->{ //
                 JSONObject json = (JSONObject)obj;
                 list.stream().forEach(iobj ->{
                     JSONObject json1 = (JSONObject)iobj;
                     if(json.getString("MOUTH") == null || json1.getString("MOUTH") == null) throw new RuntimeException("存在有误数据，月份匹配有误");
                     if(Objects.equals(json.getString("MOUTH"),json1.getString("MOUTH")))  json.putAll(json1);
                 });
             });
             doList = moththList;
         }

         //增加同期阶段数据
         if(lastStage){
             JSONObject lastStateJson = new JSONObject();
             lastStateJson.putAll(json);
             lastStateJson.put("DATE_START",getFirstDayDateOfMonth(DateUtil.add(this.startDate,Calendar.MONTH,-1)));
             lastStateJson.put("DATE_END",DateUtil.parse(com.apestech.framework.util.DateUtil.getEndDate(DateUtil.format(getLastDayDateOfMonth(DateUtil.add(this.startDate,Calendar.MONTH,-1)),DateUtil.SHOW_DATETIME_FORMAT)),DateUtil.SHOW_DATETIME_FORMAT));

             List currentState = findByAddressAndCondition(address,lastStateJson); //查询

             doList.stream().forEach(json ->{
                 JSONObject jsonRe = (JSONObject)json;
                 currentState.stream().forEach(cjson->{
                     JSONObject cjsonRe = (JSONObject)cjson;
                     dealStateDate(jsonRe,cjsonRe);
                 });
             });
         }


         t = doProcess((T) doList); //处理
         return resultMap(t); //返回结果
     }

    protected void init(JSONObject json){
        String startStr = json.getString("DATE_START");
        String endStr = json.getString("DATE_END");
        if(startStr.contains("T") && startStr.contains("Z")){
            this.startDate = DateUtil.parseUTC(startStr);
            this.endDate = DateUtil.parseUTC(endStr);
        }else{
            throw new RuntimeException("dateFomat Failed");
        }

    }

    protected  void dealStateDate(JSONObject jsonRe, JSONObject cjsonRe){}; //同上一个月对比处理数据

    protected abstract R resultMap(T t); //对处理出的结果进行格式化
    protected abstract T doProcess(T t ); //对查询出来的结果进行一次处理


    void checkTime(JSONObject json){
        if(json.get("DATE_START") == null && json.get("DATE_END") == null) throw new RuntimeException("必须传入时间");
        if(json.get("DATE_START") != null && json.get("DATE_END") == null) throw new RuntimeException("传入参数有误：结束时间");
        if(json.get("DATE_START") == null && json.get("DATE_END") != null) throw new RuntimeException("传入参数有误：开始时间");

        Date start = null;
        Date end = null;

        try {
            //时间格式转化 (用这套的都是utc格式的，所以不用判断了)
            String startStr = json.getString("DATE_START");
            String endStr = json.getString("DATE_END");
            if(startStr.contains("T") && startStr.contains("Z")){
                start = DateUtil.parseUTC(startStr);
                end = DateUtil.parseUTC(endStr);
                json.put("DATE_START",start);
                json.put("DATE_END",end);
            }else{
                start = json.getDate("DATE_START");
                end = json.getDate("DATE_END");
            }
        }catch (Exception e){
            throw new RuntimeException("传入参数有误：" + e.getMessage());
        }
        //最大时间不能超过一年
        Calendar startCalendar = Calendar.getInstance();
        startCalendar.setTime(start);
        Calendar endCalendar = Calendar.getInstance();
        endCalendar.setTime(end);
        if(endCalendar.get(Calendar.MONTH) - startCalendar.get(Calendar.MONTH) > maxMonth) throw new RuntimeException("时间间隔不能超过12个月");
    }


    /**
     * 构建一个开始到结束的年月数组
     * @param sDate
     * @param eDate
     * @return
     */
    protected static List<ArrayList> obtainMonthList(Date sDate, Date eDate){
        List list = new ArrayList();
        Date ssDate = getFirstDayDateOfMonth(sDate);
        Date eeDate = getFirstDayDateOfMonth(eDate);
        int i = 0;
        do{
            i ++;
            JSONObject reJSON = new JSONObject();
            reJSON.put("MOUTH", DateUtil.format(ssDate,"YYYY-MM"));
            if(ssDate.before(eDate)) list.add(reJSON);
            ssDate = DateUtil.add(ssDate,Calendar.MONTH,1);
        }while (!ssDate.after(eDate) && i< 50);
        return  list;
    }


    /**
     * 获取传入日期的第一天
     * @param date
     * @return
     */
    protected static Date getFirstDayDateOfMonth(Date date){
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        int first = cal.getActualMinimum(Calendar.DAY_OF_MONTH);
        cal.set(Calendar.DAY_OF_MONTH, first);
        return cal.getTime();
    }


    /**
     * 获取传入日期的月最后一天
     * @param date
     * @return
     */
    protected static Date getLastDayDateOfMonth(Date date){
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        int last = cal.getActualMaximum(Calendar.DAY_OF_MONTH);
        cal.set(Calendar.DAY_OF_MONTH, last);
        return cal.getTime();
    }


//    protected static java.util.Date parseUTC(String source) {
//        Calendar calendar = Calendar.getInstance();
//        try {
//            calendar.setTime(new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'").parse(source));
//        } catch (Exception e) {
//            e.printStackTrace();
//        }
//        return new java.util.Date(calendar.getTimeInMillis());
//    }
}